package mx.com.sinformex.simbel.db.dao.impl;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import mx.com.sinformex.simbel.db.dao.IDatabaseStructureExtractor;
import mx.com.sinformex.simbel.db.dao.IReportDataAccess;
import mx.com.sinformex.simbel.db.eos.Report;

/**
 * @author Oscar Ivan Hernandez Ventura [ oscar at sinformex dot com dot mx]
 *
 * @version $ Id : JdbcReportDataAccess.java , v 1.0 13/05/2009 angellore $
 */
public class JdbcReportDataAccess implements IReportDataAccess, IDatabaseStructureExtractor {

	private final Log log = LogFactory.getLog(getClass());
	private Map<String, SimpleJdbcTemplate> templates = new HashMap<String,SimpleJdbcTemplate>();
	private Map<String, BasicDataSource> datasources = new HashMap<String,BasicDataSource>();
	
	public List<Map<String, Object>> executeFullReport(Report report, Object... args) throws SQLException, BadSqlGrammarException {
		if(log.isDebugEnabled()) {
			String argslist = "";
			for(Object o : args) {
				argslist = String.format("%s %s", argslist, o);
			}
			log.debug(String.format("Exec report %d : %s and params %s", report.getReportId(), report.getQuery(), argslist));
		}
		SimpleJdbcTemplate template = getTemplateByName(report.getDatasourceName(), report);
		List<Map<String, Object>> rows = template.queryForList(report.getQuery(), args);
		return rows;
	}	
	
	private SimpleJdbcTemplate getTemplateByName(String name, Report report) {
		SimpleJdbcTemplate template = templates.get(name);
		if(template == null) {
			template = new SimpleJdbcTemplate(getDatasource(name, report));
			templates.put(name, template);
			
		}
		return template;
	}
	
	private BasicDataSource getDatasource(String name, Report report) {
		BasicDataSource ds = datasources.get(name);
		if(ds == null) {
			ds = new BasicDataSource();
			ds.setDriverClassName(report.getDatasource().getDriver());
			ds.setPassword(report.getDatasource().getPassword());
			ds.setUsername(report.getDatasource().getUsername());
			ds.setUrl(report.getDatasource().getUrl());
			datasources.put(name, ds);
		}
		return ds;
	}

	public Connection getConnection(Report report) {
		try {
			return getDatasource(report.getDatasourceName(), report).getConnection();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public Map<String, List<Map<String, String>>> getStructure(Report report) {
		Connection conn = getConnection(report);
		try {
			DatabaseMetaData metaData = conn.getMetaData();
			ResultSet rs = metaData.getTablePrivileges(null, null, "%");
			while(rs.next()) {
				System.out.println(rs.getString(3));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

}
